/*
 * Marmoset Add-In for Microsoft Visual Studio
 *
 * Copyright (C) 2007, David H. Hovemeyer
 * Copyright (C) 2007, Fidel K. Estrella
 *
 * This program is free software licensed under the
 * terms of the GNU General Public License, version 2.
 * See the file "COPYING.txt" for details.
 */

using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Extensibility;
using EnvDTE;
using EnvDTE80;

namespace Marmoset
{
    /// <summary>
    /// The Exporter handles the mechanics of exporting the currently-open
    /// solution into a zip file.
    /// </summary>
    class Exporter : IDisposable
    {
        #region Private Fields
        /// <summary>
        /// Private fields for the Exporter object.
        /// </summary>
        protected Solution _solution;
        protected DebugOutput _debugOut;
        private string _exportFileName; // only used when the output file is chosen through the Save dialog
        private FileStream _outputStream;
        private SolutionFileCollector _collector;
        private bool _outputStreamClosed;
        #endregion

        #region Constructor
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="solution">the Solution to export</param>
        public Exporter(Solution solution)
        {
            this._solution = solution;
        }
        #endregion

        #region Public Members
        /// <summary>
        /// Set DebugOutput.
        /// </summary>
        /// <param name="debugOut">the DebugOutput to use</param>
        public void SetDebugOutput(DebugOutput debugOut)
        {
            _debugOut = debugOut;
        }

        /// <summary>
        /// Show a file chooser dialog to allow the user to choose
        /// the name of the exported zip file.
        /// </summary>
        /// <returns>true if file was chosen successfully, false if file was not chosen successfully</returns>
        public bool ChooseExportFileName()
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "zip files (*.zip)|*.zip|All files (*.*)|*.*";
            dialog.FilterIndex = 0;
            dialog.RestoreDirectory = true;

            if (dialog.ShowDialog() != DialogResult.OK)
            {
                return false;
            }

            _exportFileName = dialog.FileName;
            return true;
        }

        /// <summary>
        /// Get the name of the exported zip file chosen by the
        /// user.  This method should only be called upon successful
        /// completion of the ChooseExportFileName() method.
        /// </summary>
        /// <returns>the name of the export file</returns>
        public string GetExportFileName()
        {
            return _exportFileName;
        }

        /// <summary>
        /// Set the output stream to which the zipfile should be written.
        /// </summary>
        /// <param name="outputStream">the output stream to which the zipfile should be written</param>
        public void SetOutputStream(FileStream outputStream)
        {
            this._outputStream = outputStream;
        }

        /// <summary>
        /// Collect all of the files that are part of the currently-open solution.
        /// This method must be called before the Export() method is called.
        /// </summary>
        public void CollectSolutionFiles()
        {
            _collector = new SolutionFileCollector(_solution);
            _collector.SetDebugOutput(_debugOut);
            _collector.CollectSolutionFiles();
        }

        /// <summary>
        /// Export the current solution into the previously selected
        /// output file or output stream.
        /// This method must only be called after calling
        /// the CollectSolutionFiles() method.
        /// </summary>
        public void Export()
        {
            if (_outputStream == null)
            {
                _outputStream = File.OpenWrite(_exportFileName);
            }

            ZipCreator zipCreator = new ZipCreator(_outputStream, _collector.GetBaseDirectory());
            using (zipCreator)
            {
                for (IEnumerator e = _collector.GetFileCollection().GetEnumerator(); e.MoveNext(); )
                {
                    string fileName = (string) e.Current;
                    zipCreator.AddInputFile(fileName);
                }
                zipCreator.CreateZipFile();
            }
            _outputStreamClosed = true;
        }

        public void Dispose()
        {
            if (_outputStream != null && !_outputStreamClosed)
            {
                _outputStream.Close();
            }
        }

        #endregion

        #region Output
        protected void WriteToOutput(string message)
        {
            if (_debugOut != null)
            {
                _debugOut.WriteToOutput(message);
            }
        }
        #endregion
    }
}
